#include <nan.h>

using v8::Boolean;
using v8::Context;
using v8::Exception;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Isolate;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::ObjectTemplate;
using v8::String;
using v8::Value;

#define CUSTOM_NAN_METHOD(className, name)                        \
  NAN_METHOD(name);                                               \
  static NAN_METHOD(static##name)                                 \
  {                                                               \
    auto obj = Nan::ObjectWrap::Unwrap<className>(info.Holder()); \
    obj->name(info);                                              \
  }

#define CUSTOM_NAN_GETTER(className, name)                        \
  NAN_GETTER(get##name);                                          \
  static NAN_GETTER(static##name##Getter)                         \
  {                                                               \
    auto obj = Nan::ObjectWrap::Unwrap<className>(info.Holder()); \
    obj->get##name(property, info);                               \
  }

#define CUSTOM_NAN_SETTER(className, name)                        \
  NAN_SETTER(set##name);                                          \
  static NAN_SETTER(static##name##Setter)                         \
  {                                                               \
    auto obj = Nan::ObjectWrap::Unwrap<className>(info.Holder()); \
    obj->set##name(property, value, info);                        \
  }

#define CUSTOM_NAN_GETTERR_HEADER(className, name)                \
  NAN_GETTER(get##name);                                          \
  static NAN_GETTER(static##name##Getter)                         \
  {                                                               \
    auto obj = Nan::ObjectWrap::Unwrap<className>(info.Holder()); \
    obj->get##name(property, info);                               \
  }                                                               \
  NAN_SETTER(set##name);                                          \
  static NAN_SETTER(static##name##Setter)                         \
  {                                                               \
    auto obj = Nan::ObjectWrap::Unwrap<className>(info.Holder()); \
    obj->set##name(property, value, info);                        \
  }

#define CUSTOM_NAN_GETTERR_CPP(className, name) \
  NAN_GETTER(className## ::get##name)

#define CUSTOM_NAN_SETTER_CPP(className, name) \
  NAN_SETTER(className## ::set##name)

#define CUSTOM_NAN_SET_METHOD(tpl, name) \
  Nan::SetMethod(tpl, #name, static##name)

#define CUSTOM_NAN_SET_PROTOTYPE_METHOD(tpl, name) \
  Nan::SetPrototypeMethod(tpl, #name, static##name)

#define CUSTOM_NAN_HANDLE_ACCESSOR(tpl, name) \
  Nan::SetAccessor(tpl, Nan::New(#name).ToLocalChecked(), static##name##Getter, static##name##Setter)
